/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Controller;

import PropertiesController.BaseModuleProperties;
import PropertiesController.DefaultProperties;
import Util.Log;
import Util.TranslatorUtils;
import Util.ValidatorUtils;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

/**
 *
 * @author Peat
 */
public abstract class BaseController extends AbstractController {

    // servlet meta data
    protected final Log log;
    private final String majorServiceId;

    protected ModelAndView mv = null;
    protected BaseModuleProperties mProperty;
    private static DefaultProperties dfProperty;

    private Map<String, Method> methods = new HashMap<String, Method>();

    static {
        dfProperty = new DefaultProperties(DefaultProperties.RESOURCE_NAME);
    }

    public BaseController(String modulePropertiesResourceName, Logger logger,
            Logger transLogger) {
        
        mProperty = new BaseModuleProperties(modulePropertiesResourceName);

        this.majorServiceId = mProperty.getModulePath();
        this.log = new Log(logger, transLogger);

        for (Method m : this.getClass().getDeclaredMethods()) {
            methods.put(m.getName(), m);
        }
    }

    protected ModelAndView handleRequestInternal(
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        String requestPage = null;

        log.stampIn();

        try{
            if(request.getSession().getAttribute("LANGS").equals("")){
               request.getSession().setAttribute("LANGS", "th");
            }
        }catch(Exception ex){
            request.getSession().setAttribute("LANGS", "th");
        }
        Map m = new HashMap();
        m.put("request", request);
        m.put("response", response);

        try {
            // real handler.
            this.mv = new ModelAndView();
            String page = mProperty.getViewPath(request);

            requestPage = page;

            if (page == null) {
                response.sendRedirect("error.html");
            } else {
                // Authentication handlings - depends on Configuration file.
                // Session -> *redirect* to login page -> if success always go to WELCOME page.
                if (mProperty.isRequiredValidSession(page) && !ValidatorUtils.validateSession(request)) {
                    response.sendRedirect("index.html");
                    return null;
                }
                // OTP -> *swap* to GenPass page -> and redirect back to org on sucess.
                // using replace content instead of redirect.
                if (mProperty.isRequiredOTP(page) && !ValidatorUtils.validateOTP(request)) {
                    page = "/UserProfile/GenPassPort";
                    // set page data
                    // Actually this should be implmented explicitly. However
                    // to keep the data handling the same approach as postpaid.
                    // and tester requirement. This is the best way to do it.
//                    this.aRes = (InfoAuthenBean) request.getSession().getAttribute("InfoAuthenBean");
//                    this.sRes = (InfoSubscriber) request.getSession().getAttribute("InfoSubscriber");
//                    String SubrNumb = null;
//                    if(this.sRes.getSendOTPSubr() == null || this.sRes.getSendOTPSubr().equals("") ){
//                        SubrNumb = this.sRes.getMasterSubrNumb();
//                    }else{
//                        SubrNumb = this.sRes.getSendOTPSubr();
//                    }
                    mv.addObject("sendOTPSubrNum", "something");
                    mv.addObject("subr_num_login", "something");
                }

                String path = "application/"+request.getSession().getAttribute("LANGS").toString()+"/";
                path += verifyPageView(page, request);  // onload
                this.mv.setViewName(path);
                setPageData(page, m);
            }
        } catch (Exception e) {
            this.mv.addObject("exception", TranslatorUtils.toJSON(e));
        }
        this.mv.addObject("RESOURCE", dfProperty.getCodeResourcePath());

        request = (HttpServletRequest) m.get("request");
        response = (HttpServletResponse) m.get("response");

        log.trans_success(request, majorServiceId, requestPage, "html request stamp.");

        return this.mv;
    }

    /**
     * Return correct pageName. This function will before set page value
     * to the ModelAndView.
     *
     * Commonly this function used in handling onload of supplied pageName
     * variable. If Such service not allows user to use that page. Replace
     * Its view with the Error Page. And also inject the error message in.
     *
     * On default (if not override) this function simply concatenate with
     * the module path.
     *
     * @param pageName
     * @return
     */
    protected String verifyPageView(String pageName, 
            HttpServletRequest request) throws Exception {
        return mProperty.getModulePath() + "/" + pageName;
    }

    protected void setPageData(String pageName, Map data) throws Exception {
        // Rourting to a function 'setPageData_'.pageName;
        String methodName = "setPageData_" + pageName;
        Method invoker = (Method) methods.get(methodName);
        if (invoker==null) {
            // do nothing just skip it
            return;
            // throw new Exception("Unsupported page data setter pageName: " + pageName);
        }
        invoker.invoke(this, data);
    }
}
